package com.cmccsi.uc.redis;

import org.apache.log4j.Logger;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.exceptions.JedisConnectionException;

import com.cmccsi.uc.session.PresenceSubscriber;
import com.cmccsi.uc.session.WORKER;
import com.thn.netty.chat.server.ExecRedisCmdErr;
import com.thn.netty.chat.util.RedisConnPool;

public class CAsyncR implements ICAsyncR {

	//public friend void AsyncRedis_reconnect_time_cb(const int fd, const short which, void *arg);
	
	//public	CAsyncR( String server, int port, WORKER w );
	//public	CAsyncR( String server, int port );
	
	//public	virtual ~CAsyncR();
	
	
	
	private static final short PST_SINGLE = 0;
	private static final short PST_GROUP=1;
	private static final short PST_DEPART=2;
	
	private static final Logger LOGGER = Logger.getLogger(CAsyncR.class.getName());
	
	@Override
	public int insertMsg2Redis(int msgType, String szValue,
			ExecRedisCmdErr rtValue) {
		// TODO Auto-generated method stub
		String szKeys;
		if ( msgType == 0 )
		{
			szKeys = "ims_msg_hist";
		}
		else if( msgType == 1 )
		{
			szKeys = "group_msg_hist";
		}
		else
		{
			return -1;
		}

		//int rslt = execCmd2AsyncRedis( "RPUSH", szKeys, szValue );
		int rslt = execCmd2AsyncRedisByBytes( "RPUSH", szKeys, szValue );
		return rslt;
	}

	@Override
	public int insertMsgStatus2Redis(int msgType, String szValue,
			ExecRedisCmdErr rtValue) {
		// TODO Auto-generated method stub
		
		String szKeys;
		if ( msgType == 0 )
		{
			szKeys = "ims_msg_status";
		}
		else if( msgType == 1 )
		{
			szKeys = "group_msg_hist_status";
		}
		else
		{
			return -1;
		}
	/*
	char szInbuf[CONN_BUF_LEN];

			memcpy(szInbuf,szValue.c_str(),szValue.length());
			szInbuf[szValue.length()] = '\0';

			LOG(INFO)<<"\npConn->huizhi1111[]:"<<pConn->in_buf_len<<":::::::::::::::";
			int i = 0;
			std::string tmpstring = "";
			while(i < szValue.length())
			{
			char tmp[4] = {'\0'};
			
				sprintf(tmp,"%02x ",szInbuf[i]);
				tmpstring += tmp;
			//LOG(INFO)<<tmp;
				i++;
			}
			LOG(INFO)<<tmpstring;
			LOG(INFO)<<"\n";
			*/
		int rslt = execCmd2AsyncRedisByBytes( "RPUSH", szKeys, szValue );

		return rslt;
	}

	@Override
	public int insertIOSPush2Redis(String szValue, ExecRedisCmdErr rtValue) {
		// TODO Auto-generated method stub
	 	String szKeys = "ims_msg_ios_push";

	 	LOGGER.info("ims_msg_ios_push::"+szValue);
		int rslt = execCmd2AsyncRedisByBytes( "RPUSH", szKeys, szValue );
		return rslt;
	}

	@Override
	public int insertSMS2BroadCast(String szValue, ExecRedisCmdErr rtValue) {
		// TODO Auto-generated method stub
		String szKeys = "sms_broadcast";

		//int rslt = execCmd2AsyncRedis( "RPUSH", szKeys, szValue );
		int rslt = execCmd2AsyncRedisByBytes( "RPUSH", szKeys, szValue );

		return rslt;
	}

	@Override
	public int addSubscriber(long ulUserId, PresenceSubscriber subscriber,
			ExecRedisCmdErr rtValue, String strDeviceType) {
		// TODO Auto-generated method stub
		long ulSubId = subscriber.getUlId();
		short type = subscriber.getUcType();

		String szSubId="";
		
		szSubId=szSubId.format("%lu", ulSubId );
		String szUserId="";
		
		szUserId=szUserId.format("%lu", ulUserId );

		String szCmd="sadd subscriber:";
		szCmd += strDeviceType ;
		szCmd += ":";
		szCmd += szSubId;
		szCmd += ":";


		String szCmdUser="sadd subscriber_user:";
		szCmdUser += strDeviceType ;
		szCmdUser += ":";
		szCmdUser += szUserId;
		szCmdUser += ":";

		switch ( type )
		{
		case PST_SINGLE:
			{
				szCmd += "users";		//单人
				szCmdUser += "users";	
			}
			break;
		case PST_GROUP:
			{
				szCmd += "groups";		//群组
				szCmdUser += "groups";	
			}
			break;
		case PST_DEPART:
			{
				szCmd += "depts";		//部门
				szCmdUser += "depts";	
			}
			break;
		default:
			{
				return -1;
			}
		}
		szCmd += " ";
		szCmd += szUserId;
		
		szCmdUser += " ";
		szCmdUser += szSubId;
		/*stringstream ssCmd;
		ssCmd << "sadd ";	//在set中存储
		ssCmd << "subscriber:";
		ssCmd << ulSubId;
		ssCmd << ":";
		switch ( type )
		{
		case PST_SINGLE:
			{
				ssCmd << "users";		//单人
			}
			break;
		case PST_GROUP:
			{
				ssCmd << "groups";		//群组
			}
			break;
		case PST_DEPART:
			{
				ssCmd << "depts";		//部门
			}
			break;
		default:
			{
				return -1;
			}
			break;
		}
		ssCmd << " ";
		ssCmd << ulUserId;

		std::string szCmd = ssCmd.str();*/
		int rslt = execCmd2AsyncRedis( szCmd );
		int rsltuser = execCmd2AsyncRedis( szCmdUser );
		if(rslt != 0 )
		return rslt;
		else
		return rsltuser;
	}

	@Override
	public int removeSubScriber(long ulUserId, PresenceSubscriber subscriber,
			ExecRedisCmdErr rtValue, String strDeviceType) {
		// TODO Auto-generated method stub
		long ulRmSubId = subscriber.getUlId();
		short type = subscriber.getUcType();

		String szRmSubId="";
		szRmSubId=szRmSubId.format("%lu", ulRmSubId );
		String szUserId="";
		szUserId=szUserId.format("%lu", ulUserId );

		String szCmd="srem subscriber:";
		szCmd += strDeviceType;
		szCmd += ":";
		szCmd += szRmSubId;
		szCmd += ":";

		String szCmdUser="srem subscriber_user:";
		szCmdUser += strDeviceType ;
		szCmdUser += ":";
		szCmdUser += szUserId;
		szCmdUser += ":";

		switch ( type )
		{
		case PST_SINGLE:
			{
				szCmd += "users";		//单人
				szCmdUser += "users";	
			}
			break;
		case PST_GROUP:
			{
				szCmd += "groups";		//群组
				szCmdUser += "groups";	
			}
			break;
		case PST_DEPART:
			{
				szCmd += "depts";		//部门
				szCmdUser += "depts";	
			}
			break;
		default:
			{
				return -1;
			}
		}

		szCmd += " ";
		szCmd += szUserId;

		szCmdUser += " ";
		szCmdUser += szRmSubId;
		
		/*stringstream ssCmd;
		ssCmd << "srem ";
		ssCmd << "subscriber:";
		ssCmd << ulRmSubId;
		ssCmd << ":";
		switch ( type )
		{
		case PST_SINGLE:
			{
				ssCmd << "users";		//单人
			}
			break;
		case PST_GROUP:
			{
				ssCmd << "groups";		//群组
			}
			break;
		case PST_DEPART:
			{
				ssCmd << "depts";		//部门
			}
			break;
		default:
			{
				return -1;
			}
			break;
		}

		ssCmd << " ";
		ssCmd << ulUserId;

		std::string szCmd = ssCmd.str();*/
		int rslt = execCmd2AsyncRedis( szCmd );

		int rsltuser = execCmd2AsyncRedis( szCmdUser );
		if(rslt != 0 )
		return rslt;
		else
		return rsltuser;
	}

	@Override
	public int setUserLoginInfo(long ulUserId, String loginInfo,
			ExecRedisCmdErr rtValue) {
		// TODO Auto-generated method stub
		String cUserId="";
		cUserId=cUserId.format("%lu", ulUserId );
		int rslt = execCmd2AsyncRedis( "HSET", "presence", cUserId, loginInfo );
		return rslt;
	}

	@Override
	public int delUserLoginInfo(long ulUserId, ExecRedisCmdErr rtValue) {
		// TODO Auto-generated method stub
		String cUserId="";
		cUserId=cUserId.format("%lu", ulUserId );
		int rslt = execCmd2AsyncRedis( "HDEL", "presence", cUserId);
		return rslt;
	}

	@Override
	public int setNotifyContent(String hashKeys, String hashValue,
			ExecRedisCmdErr rtValue) {
		// TODO Auto-generated method stub
		int rslt = execCmd2AsyncRedis( "HSET", "notify" ,hashKeys, hashValue );
		return rslt;
	}

	@Override
	public int delNotifyContent(String hashKeys, ExecRedisCmdErr rtValue) {
		// TODO Auto-generated method stub
		int rslt = execCmd2AsyncRedis( "HDEL", "notify", hashKeys );
		return rslt;
	}

	@Override
	public int setAppMsgContent(String szValue, ExecRedisCmdErr rtValue) {
		// TODO Auto-generated method stub
		int rslt = execCmd2AsyncRedis( "RPUSH", "app_push_msg", szValue );
		return rslt;
	}

	@Override
	public int deleteUserSession(String userId, ExecRedisCmdErr rtValue) {
		// TODO Auto-generated method stub
		int rslt = execCmd2AsyncRedis( "HDEL", "usersession", userId );
		return rslt;
	}

	@Override
	public int deleteSession(String szSession, ExecRedisCmdErr rtValue) {
		// TODO Auto-generated method stub
		String szCmd="DEL ";
		szCmd += szSession;
		int rslt = execCmd2AsyncRedis( szCmd );
		return rslt;
	}

	@Override
	public int setIosTokenByUserid(String szUserId, String szIosToken,
			ExecRedisCmdErr rtValue) {
		// TODO Auto-generated method stub
		int rslt = execCmd2AsyncRedis( "HSET", "iostoken" ,szUserId, szIosToken );
		return rslt;
	}

	@Override
	public int delIosTokenByUserId(String szUserId, ExecRedisCmdErr rtValue) {
		// TODO Auto-generated method stub
		int rslt = execCmd2AsyncRedis( "HDEL", "iostoken", szUserId );
		return rslt;
	}

	@Override
	public int insertPreDelUserSession(String userid, String strSessionId,
			ExecRedisCmdErr rtValue) {
		// TODO Auto-generated method stub
		int rslt = execCmd2AsyncRedis( "HSET", "predelsession" ,strSessionId, userid);
		return rslt;
	}

	@Override
	public int insertUplinkSmsContent(String hashId, String hashValue,
			ExecRedisCmdErr rtValue) {
		// TODO Auto-generated method stub
		int rslt = execCmd2AsyncRedis( "HSET", "SMS_msg_uplink", hashId, hashValue );
		return rslt;
	}

	@Override
	public int insertPreSendSmsContent(String szJosn, ExecRedisCmdErr rtValue) {
		// TODO Auto-generated method stub
		int rslt = execCmd2AsyncRedisByBytes( "RPUSH", "sms_presend", szJosn );
		return rslt;
	}

	@Override
	public int execCmd2AsyncRedis(String szCmd) {
		// TODO Auto-generated method stub		
		//DEL  srem sadd		
		if (szCmd.isEmpty()) {
			return -1;
		}

		String szCmdData = "";
		szCmdData = szCmd;

		String keys[] = szCmdData.split(" ");
		String cmd = keys[0];

		Jedis sc = null;
		boolean broken = false;
		try {
			sc = RedisConnPool.getJedis();
			switch (cmd) {
			case "DEL":
				sc.del(keys[1]);
			case "srem":
				sc.srem(keys[1], keys[2]);
			case "sadd":
				sc.sadd(keys[1], keys[2]);
			}
			return 0;
		} catch (JedisConnectionException e) {
			LOGGER.error(e.getMessage(), e);
			broken = true;
			return -1;
		} finally {
			RedisConnPool.returnJedis(sc, broken);
		}		
	}

	@Override
	public int execCmd2AsyncRedis(String szCmd, String szKeys, String szValues) {
		// TODO Auto-generated method stub
		
		//HDEL RPUSH
		
		if (szCmd.isEmpty()) {
			return -1;
		}
		String szCmdData = "";
		szCmdData = szCmd;

		String keys[] = szCmdData.split(" ");
		String cmd = keys[0];

		Jedis sc = null;
		boolean broken = false;
		try {
			sc = RedisConnPool.getJedis();
			switch (szCmd) {
			case "HDEL":
				sc.hdel(szKeys,szValues);
			case "RPUSH":
				sc.rpushx(szKeys,szValues);
			}
			return 0;
		} catch (JedisConnectionException e) {
			LOGGER.error(e.getMessage(), e);
			broken = true;
			return -1;
		} finally {
			RedisConnPool.returnJedis(sc, broken);
		}	
	}

	@Override
	public int execCmd2AsyncRedisByBytes(String szCmd, String szKeys,
			String szValues) {
		// TODO Auto-generated method stub
		String preCmd = szCmd + " " + szKeys + " " + szValues;
		String preData = "";		
		preData=preCmd;

		int size =szValues.length();
		int idx = szCmd.indexOf("RPUSH" );
		if ( idx == -1 )
		{
			return -1;
		}
	/*
		char szInbuf[CONN_BUF_LEN];

			memcpy(szInbuf,szValues.c_str(),szValues.length());
			szInbuf[szValues.length()] = '\0';

			LOG(INFO)<<"\npConn->huizhi2222:"<<szValues.length()<<"::::::::::size:::::"<<size;
			int i = 0;
			std::string tmpstring = "";
			while(i < szValues.length())
			{
			char tmp[4] = {'\0'};
			
				sprintf(tmp,"%02x ",szInbuf[i]);
				tmpstring += tmp;
			//LOG(INFO)<<tmp;
				i++;
			}
			LOG(INFO)<<tmpstring<<"szValues"<<szValues;
			LOG(INFO)<<"\n";
			*/
		
		Jedis sc = null;
		boolean broken = false;
		int rslt=0;
		try {
			sc = RedisConnPool.getJedis();
			String[] keys=preCmd.split(" ");
			sc.rpush(keys[1], keys[2]);
			//values=sc.lrange(keys[1], Long.parseLong(keys[2]), Long.parseLong(keys[3]));
		} catch (JedisConnectionException e) {
			LOGGER.error(e.getMessage(), e);				
			//rtValue.setSzErrorCodeStr(e.getMessage());
			//rtValue.setErrorCode(-1);
			broken = true;	
			rslt=-1;
		} finally {
			RedisConnPool.returnJedis(sc, broken);
		}
		return rslt;
	}

	@Override
	public int execCmd2AsyncRedis(String szCmd, String szHashName,
			String szHashKey, String szHashValue) {
		// TODO Auto-generated method stub
		if (szCmd.isEmpty()) {
			return -1;
		}
		
		int idx = szCmd.indexOf("HSET" );
		if ( idx == -1 )
		{
			return -1;
		}
		//HSET		

		Jedis sc = null;
		boolean broken = false;
		try {
			sc.hset(szHashName, szHashKey, szHashValue);
			return 0;
		} catch (JedisConnectionException e) {
			LOGGER.error(e.getMessage(), e);
			broken = true;
			return -1;
		} finally {
			RedisConnPool.returnJedis(sc, broken);
		}	
	}

//	@Override
//	public void releaseConn() {
//		// TODO Auto-generated method stub
//		
//	}
	
	
	//public	static void connectAsyncCallback( redisAsyncContext *c, int status );
	//public	static void disconnectAsyncCallback( const redisAsyncContext *c, int status );
	//public	static void insertRedisCallback( redisAsyncContext *c, void *r, void *privdata );
	//public	static void AsyncRedis_reconnect_time_cb(const int fd, const short which, void *arg);
	//public	static void AddReconnectTimer(_WORKER *w, CAsyncR* pAsyncR);
	//public	virtual int Reconnect(const redisAsyncContext *asyncRedis);
	//public	redisAsyncContext *m_asyncRdisContext;							//hiredis的实例化连接
		
private	String m_szServerIp;
private	int m_port;
private	WORKER owner;
private	int m_nConnectStatus;

}
